﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace FormatTest
{
    /// <summary>
    /// 序参数集
    /// </summary>
    public class seq_parameter_set_rbsp : base_func
    {
        public seq_parameter_set_rbsp()
        { }

        public nal_unit nal_unit
        {
            get;
            set;
        }

        /// <summary>
        /// 解码图像顺序的计数方法
        /// </summary>
        public int pic_order_cnt_type;

        public int chroma_format_idc;

        public int mb_adaptive_frame_field_flag;

        public int pic_width_in_mbs_minus1;

        public int pic_height_in_map_units_minus1;

        public seq_parameter_set_rbsp(string bytes)
        {
            this.bytes = bytes;
            this.profile_idc = TwoToTen(read_bits(8));
            this.constraint_set0_flag = TwoToTen(read_bits(1));
            this.constraint_set1_flag = TwoToTen(read_bits(1));
            this.constraint_set2_flag = TwoToTen(read_bits(1));
            this.constraint_set3_flag = TwoToTen(read_bits(1));
            this.reserved_zero_4bits = TwoToTen(read_bits(4));
            this.level_idc = TwoToTen(read_bits(8));
            this.seq_parameter_set_id = columbus_ue();
            if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144)
            {
                chroma_format_idc = columbus_ue();
                if (chroma_format_idc == 3)
                {
                    residual_colour_transform_flag = TwoToTen(read_bits(1));
                }
                var bit_depth_luma_minus8 = columbus_ue();
                var bit_depth_chroma_minus8 = columbus_ue();
                var qpprime_y_zero_transform_bypass_flag = TwoToTen(read_bits(1));
                var seq_scaling_matrix_present_flag = Convert.ToInt32(read_bits(1));
                if (seq_scaling_matrix_present_flag != 0)
                {
                    var seq_scaling_list_present_flag = new List<int>();
                    for (var i = 0; i < 8; i++)
                    {
                        seq_scaling_list_present_flag[i] = Convert.ToInt32(read_bits(1));
                        if (seq_scaling_list_present_flag[i] != 0)
                        {
                            if (i < 6)
                            {
                                //此处list的长度为16
                                var list = new List<int>();
                                scaling_list(list, 16, false);
                            }
                            else
                            {
                                //此处list的长度为64
                                var list = new List<int>();
                                scaling_list(list, 16, false);
                            }
                        }
                    }
                }
            }
            var log2_max_frame_num_minus4 = Convert.ToInt32(columbus_ue());
            pic_order_cnt_type = Convert.ToInt32(columbus_ue());
            if (pic_order_cnt_type == 0)
            {
                var log2_max_pic_order_cnt_lsb_minus4 = columbus_ue();
            }
            else if (pic_order_cnt_type == 1)
            {
                delta_pic_order_always_zero_flag = Convert.ToInt32(read_bits(1));
                var offset_for_non_ref_pic = columbus_se();
                var offset_for_top_to_bottom_field = columbus_se();
                var num_ref_frames_in_pic_order_cnt_cycle = columbus_ue();
                var offset_for_ref_frame = new List<int>();
                for (var i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++)
                {
                    offset_for_ref_frame[i] = columbus_se();
                }
            }
            var num_ref_frames = columbus_ue();
            var gaps_in_frame_num_value_allowed_flag = read_one_bit();
            pic_width_in_mbs_minus1 = columbus_ue();
            pic_height_in_map_units_minus1 = columbus_ue();
            frame_mbs_only_flag = read_one_bit();
            if (frame_mbs_only_flag == 0)
            {
                mb_adaptive_frame_field_flag = read_one_bit();
            }
            var direct_8x8_inference_flag = read_bits(1);
            var frame_cropping_flag = read_one_bit();
            if (frame_cropping_flag != 0)
            {
                var frame_crop_left_offset = columbus_ue();
                var frame_crop_right_offset = columbus_ue();
                var frame_crop_top_offset = columbus_ue();
                var rame_crop_bottom_offset = columbus_ue();
            }
            var vui_parameters_present_flag = read_one_bit();
            if (vui_parameters_present_flag != 0)
            {
                vui_parameters();
            }
            rbsp_trailing_bits();
        }

        public int frame_mbs_only_flag;

        public int profile_idc;

        public int constraint_set0_flag;

        public int constraint_set1_flag;

        public int constraint_set2_flag;

        public int constraint_set3_flag;

        public int reserved_zero_4bits;

        public int level_idc;

        public int seq_parameter_set_id;

        public int residual_colour_transform_flag;

        public int delta_pic_order_always_zero_flag;

        private void vui_parameters()
        {
            var aspect_ratio_info_present_flag = Convert.ToInt32(read_bits(1));
            if (aspect_ratio_info_present_flag != 0)
            {
                var aspect_ratio_idc = Convert.ToInt32(read_bits(8), 10);
                //此处原伪代码为 aspect_ratio_idc==Extended_SAR 经过查表得知 Extended_SAR=255
                if (aspect_ratio_idc == 255)
                {
                    var sar_width = Convert.ToInt32(read_bits(16), 10);
                    var sar_height = Convert.ToInt32(read_bits(16), 10);
                }
            }
            var overscan_info_present_flag = Convert.ToInt32(read_bits(1));
            if (overscan_info_present_flag != 0)
            {
                var overscan_appropriate_flag = read_bits(1);
            }
            var video_signal_type_present_flag = Convert.ToInt32(read_bits(1));
            if (video_signal_type_present_flag != 0)
            {
                var video_format = read_bits(3);
                var video_full_range_flag = read_bits(1);
                var colour_description_present_flag = Convert.ToInt32(read_bits(1));
                if (colour_description_present_flag != 0)
                {
                    var colour_primaries = read_bits(8);
                    var ransfer_characteristics = read_bits(8);
                    var matrix_coefficients = read_bits(8);
                }
            }
            var chroma_loc_info_present_flag = Convert.ToInt32(read_bits(1));
            if (chroma_loc_info_present_flag != 0)
            {
                var chroma_sample_loc_type_top_field = columbus_ue();
                var chroma_sample_loc_type_bottom_field = columbus_ue();
            }
            var timing_info_present_flag = Convert.ToInt32(read_bits(1));
            if (timing_info_present_flag != 0)
            {
                var num_units_in_tick = read_bits(32);
                var time_scale = read_bits(32);
                var fixed_frame_rate_flag = read_bits(1);
            }
            var nal_hrd_parameters_present_flag = Convert.ToInt32(read_bits(1));
            if (nal_hrd_parameters_present_flag != 0)
            {
                hrd_parameters();
            }
            var vcl_hrd_parameters_present_flag = Convert.ToInt32(read_bits(1));
            if (vcl_hrd_parameters_present_flag != 0)
            {
                hrd_parameters();
            }
            if (nal_hrd_parameters_present_flag != 0 || vcl_hrd_parameters_present_flag != 0)
            {
                var low_delay_hrd_flag = read_bits(1);
            }
            var pic_struct_present_flag = read_bits(1);
            var bitstream_restriction_flag = Convert.ToInt32(read_bits(1));
            if (bitstream_restriction_flag != 0)
            {
                var motion_vectors_over_pic_boundaries_flag = read_bits(1);
                var max_bytes_per_pic_denom = columbus_ue();
                var max_bits_per_mb_denom = columbus_ue();
                var log2_max_mv_length_horizontal = columbus_ue();
                var log2_max_mv_length_vertical = columbus_ue();
                var num_reorder_frames = columbus_ue();
                var max_dec_frame_buffering = columbus_ue();

            }
        }

        private void hrd_parameters()
        {
            var cpb_cnt_minus1 = columbus_ue();
            var bit_rate_scale = read_bits(4);
            var cpb_size_scale = read_bits(4);
            var bit_rate_value_minus1 = new List<int>();
            var cpb_size_value_minus1 = new List<int>();
            var cbr_flag = new List<int>();
            for (var SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; SchedSelIdx++)
            {
                bit_rate_value_minus1[SchedSelIdx] = columbus_ue();
                cpb_size_value_minus1[SchedSelIdx] = columbus_ue();
                cbr_flag[SchedSelIdx] = Convert.ToInt32(read_bits(1));
            }
            var initial_cpb_removal_delay_length_minus1 = read_bits(5);
            var cpb_removal_delay_length_minus1 = read_bits(5);
            var dpb_output_delay_length_minus1 = read_bits(5);
            var time_offset_length = read_bits(5);
        }




        private void scaling_list(List<int> scalingList, int sizeOfScalingList, bool useDefaultScalingMatrixFlag)
        {
            var lastScale = 8;
            var nextScale = 8;
            for (var j = 0; j < sizeOfScalingList; j++)
            {
                if (nextScale != 0)
                {
                    var delta_scale = columbus_se();
                    nextScale = (lastScale + delta_scale + 256) % 256;
                    useDefaultScalingMatrixFlag = (j == 0 && nextScale == 0);
                }
                scalingList[j] = (nextScale == 0) ? lastScale : nextScale;
                lastScale = scalingList[j];
            }
        }

    }
}
